<template>
    <div ref="editor" class="main"></div>
</template>

<script>
import * as monaco from "monaco-editor";
import createSqlCompleter from "./util/sql-completion";
import createJavascriptCompleter from "./util/javascript-completion";
import createPythonCompleter from "./util/python-completion";
import registerLanguage from "./util/log-language";
const global = {};

const getHints = model => {
    let id = model.id.substring(6);
    return (global[id] && global[id].hints) || [];
};
monaco.languages.registerCompletionItemProvider(
    "sql",
    createSqlCompleter(getHints)
);
monaco.languages.registerCompletionItemProvider(
    "javascript",
    createJavascriptCompleter(getHints)
);
monaco.languages.registerCompletionItemProvider(
    "python",
    createPythonCompleter(getHints)
);
registerLanguage(monaco);
/**
 * monaco options
 * https://microsoft.github.io/monaco-editor/api/interfaces/monaco.editor.istandaloneeditorconstructionoptions.html
 */
export default {
    props: {
        options: {
            type: Object,
            default() {
                return {};
            }
        },
        value: {
            type: String,
            required: true
        },
        language: {
            type: String
        },
        hints: {
            type: Array,
            default() {
                return [];
            }
        }
    },
    name: "BaseMonacoEditor",
    data() {
        return {
            editorInstance: null,
            defaultOptions: {
                theme: "vs",
                fontSize: 14
            }
        };
    },
    watch: {
        value() {
            if (this.value !== this.editorInstance.getValue()) {
                this.editorInstance.setValue(this.value);
            }
        }
    },
    mounted() {
        this.initEditor();
        global[this.editorInstance._id] = this;
        window.addEventListener("resize", this.layout);
    },
    destroyed() {
        this.editorInstance.dispose();
        global[this.editorInstance._id] = null;
        window.removeEventListener("resize", this.layout);
    },
    methods: {
        layout() {
            this.editorInstance.layout();
        },
        undo() {
            this.editorInstance.trigger("anyString", "undo");
            this.onValueChange();
        },
        redo() {
            this.editorInstance.trigger("anyString", "redo");
            this.onValueChange();
        },
        getOptions() {
            let props = { value: this.value };
            this.language !== undefined && (props.language = this.language);
            let options = Object.assign(
                {},
                this.defaultOptions,
                this.options,
                props
            );
            return options;
        },
        onValueChange() {
            this.$emit("input", this.editorInstance.getValue());
            this.$emit("change", this.editorInstance.getValue());
        },
        initEditor() {
            this.MonacoEnvironment = {
                getWorkerUrl: function() {
                    return "./editor.worker.bundle.js";
                }
            };

            this.editorInstance = monaco.editor.create(
                this.$refs.editor,
                this.getOptions()
            );
            this.editorInstance.onContextMenu(e => {
                this.$emit("contextmenu", e);
            });
            this.editorInstance.onDidChangeModelContent(() => {
                this.onValueChange();
            });
            this.editorInstance.addCommand(
                monaco.KeyMod.CtrlCmd | monaco.KeyCode.KEY_S,
                () => {
                    this.$emit("save", this.editorInstance.getValue());
                }
            );
        }
    }
};
</script>

<style scoped>
.main /deep/ .view-lines * {
    font-family: Consolas, "Courier New", monospace !important;
}
</style>
